﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.SaveComponentAs.CApSaveComponentAsNewPrototypeLogic
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Resources;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.SaveComponentAs;

public class CApSaveComponentAsNewPrototypeLogic
{
  private CApSaveComponentAsNewPrototypeLogic.Status _status;
  private List<TxObjectColorData> _colorData;
  private List<Tuple<ITxDisplayableObject, TxDisplayableObjectVisibility>> _visibilityData;
  private List<TxObjectDisplayModeData> _displayModeData;
  private bool _invokeUi = true;

  public bool InvokeUi
  {
    set => this._invokeUi = value;
  }

  public bool Execute()
  {
    this._status = CApSaveComponentAsNewPrototypeLogic.Status.Unknown;
    ITxComponent sourceComponent = this.GetSourceComponent();
    if (sourceComponent == null)
    {
      this.OutputErrorMessage(sourceComponent);
      return false;
    }
    if (!this.ValidateComponent(sourceComponent))
    {
      this.OutputErrorMessage(sourceComponent);
      return false;
    }
    string newPath = this.ComputeNewPath(sourceComponent);
    if (string.IsNullOrEmpty(newPath))
    {
      this.OutputErrorMessage(sourceComponent);
      return false;
    }
    if (this.CreateNewPrototype(sourceComponent, newPath))
      return true;
    this.OutputErrorMessage(sourceComponent);
    return false;
  }

  private bool ValidateComponent(ITxComponent component)
  {
    if (CApSaveComponentAsNewPrototypeLogic.IsNewComponent(component as ITxStorable))
    {
      this._status = CApSaveComponentAsNewPrototypeLogic.Status.ComponentHasNoPrototype;
      return false;
    }
    if (!this.DoesEquipmentHaveNewSubComponent(component))
      return true;
    this._status = CApSaveComponentAsNewPrototypeLogic.Status.EquipmentHasSubComponentWithNoPrototype;
    return false;
  }

  private bool DoesEquipmentHaveNewSubComponent(ITxComponent component)
  {
    if (TxApplication.PlatformType == 1 || !component.IsEquipment)
      return false;
    foreach (ITxObject directDescendant in (Collection<ITxObject>) (component as ITxObjectCollection).GetDirectDescendants((ITxTypeFilter) new TxTypeFilter(typeof (ITxComponent))))
    {
      if (CApSaveComponentAsNewPrototypeLogic.IsNewComponent(directDescendant as ITxStorable))
        return true;
    }
    return false;
  }

  private void OutputErrorMessage(ITxComponent component)
  {
    if (!this._invokeUi || this._status == CApSaveComponentAsNewPrototypeLogic.Status.CancelClicked)
      return;
    MessageBoxIcon messageBoxIcon = MessageBoxIcon.Hand;
    string str;
    if (this._status == CApSaveComponentAsNewPrototypeLogic.Status.ComponentHasNoPrototype)
      str = this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_COMPONENT_NOT_IN_LIBRARY");
    else if (this._status == CApSaveComponentAsNewPrototypeLogic.Status.EquipmentHasSubComponentWithNoPrototype)
    {
      TxObjectList<ITxComponent> newSubComponents = this.GetNewSubComponents(component);
      str = this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_SUB_COMPONENT_NOT_IN_LIBRARY");
      foreach (ITxComponent itxComponent in (Collection<ITxComponent>) newSubComponents)
        str = $"{str}\n\t{((ITxObject) itxComponent).Name}";
    }
    else
      str = this._status != CApSaveComponentAsNewPrototypeLogic.Status.ComponentNotInSysroot ? (this._status != CApSaveComponentAsNewPrototypeLogic.Status.CannotOpenForModeling ? string.Format(this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_FAIL"), (object) ((ITxObject) component).Name) : string.Format(this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_FAIL_SET_MODELING"), (object) ((ITxObject) component).Name)) : (TxApplication.PlatformType != 3 ? this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_COMPONENT_NOT_UNDER_SYSROOT") : this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_COMPONENT_NOT_UNDER_LIBRARY_ROOT"));
    int num = (int) TxMessageBox.Show(str, this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_CMD_NAME"), MessageBoxButtons.OK, messageBoxIcon);
  }

  private TxObjectList<ITxComponent> GetNewSubComponents(ITxComponent component)
  {
    TxObjectList<ITxComponent> newSubComponents = new TxObjectList<ITxComponent>();
    foreach (ITxObject directDescendant in (Collection<ITxObject>) (component as ITxObjectCollection).GetDirectDescendants((ITxTypeFilter) new TxTypeFilter(typeof (ITxComponent))))
    {
      if (CApSaveComponentAsNewPrototypeLogic.IsNewComponent(directDescendant as ITxStorable))
        ((Collection<ITxComponent>) newSubComponents).Add(directDescendant as ITxComponent);
    }
    return newSubComponents;
  }

  private bool CreateNewPrototype(ITxComponent sourceComponent, string newPath)
  {
    Cursor current = Cursor.Current;
    Cursor.Current = Cursors.WaitCursor;
    ITxComponent newComponent = this.CreateNewComponent(sourceComponent);
    if (newComponent == null)
      return false;
    ((ITxObject) newComponent).Name = Path.GetFileNameWithoutExtension(newPath);
    if (!this.EndModelNewComponent(newComponent, newPath))
      return false;
    newComponent.SetModelingScope();
    Cursor.Current = current;
    return true;
  }

  private bool EndModelNewComponent(ITxComponent newComponent, string newPath)
  {
    try
    {
      newComponent.EndModeling(newPath);
    }
    catch (Exception ex)
    {
      ((ITxObject) newComponent).Delete();
      return false;
    }
    return true;
  }

  private string ComputeNewPath(ITxComponent sourceComponent)
  {
    string empty = string.Empty;
    string componentPath = TxComponentEx.GetComponentPath(sourceComponent, false);
    if (!this.ValidateInitialPath(ref componentPath))
      return string.Empty;
    string uniqueComponentName = this.GetUniqueComponentName(componentPath);
    return !this._invokeUi ? Path.Combine(Path.GetDirectoryName(componentPath), uniqueComponentName) : this.PickNewPath(componentPath, uniqueComponentName);
  }

  [DllImport("ComponentOperations.dll", CallingConvention = CallingConvention.Cdecl)]
  [return: MarshalAs(UnmanagedType.I1)]
  public static extern bool OpenSaveComponentDialog(
    string currPath,
    StringBuilder newPath,
    int strlen,
    string fileName,
    bool enableChangeFileName,
    bool useLastPath = false,
    bool canOverwrite = true);

  private string PickNewPath(string sourcePath, string newFilename)
  {
    string empty = string.Empty;
    int num = 260;
    StringBuilder newPath = new StringBuilder(num);
    for (; !this.ValidateNewPath(empty); empty = newPath.ToString())
    {
      bool enableChangeFileName = true;
      bool useLastPath = false;
      bool canOverwrite = false;
      if (!CApSaveComponentAsNewPrototypeLogic.OpenSaveComponentDialog(sourcePath, newPath, num, newFilename, enableChangeFileName, useLastPath, canOverwrite))
      {
        this._status = CApSaveComponentAsNewPrototypeLogic.Status.CancelClicked;
        return string.Empty;
      }
    }
    return empty;
  }

  private ITxComponent CreateNewComponent(ITxComponent sourceComponent)
  {
    bool isOpenForModeling = sourceComponent.IsOpenForModeling;
    if (!isOpenForModeling)
    {
      this.CollectGraphicInstanceInfo(sourceComponent);
      if (!this.SetSourceToModeling(sourceComponent))
        return (ITxComponent) null;
    }
    ITxComponent newComponent = this.CopyComponent(sourceComponent);
    this.HandleReadOnlyComponent(newComponent);
    if (!isOpenForModeling)
    {
      if (!this.ReloadSource(sourceComponent) && ((ITxObject) newComponent).IsValid())
      {
        ((ITxObject) newComponent).Delete();
        return (ITxComponent) null;
      }
      this.ApplyGraphicInstanceInfo(sourceComponent);
    }
    return newComponent;
  }

  private void HandleReadOnlyComponent(ITxComponent newComponent)
  {
    foreach (FileInfo file in new DirectoryInfo(TxComponentEx.Get3DDataFullPath(newComponent as ITxStorable)).GetFiles())
    {
      if (file.IsReadOnly)
        file.IsReadOnly = false;
    }
  }

  private void CollectGraphicInstanceInfo(ITxComponent component)
  {
    this.CollectColor(component);
    this.CollectVisibility(component);
    this.CollectDisplayModel(component);
  }

  private void CollectColor(ITxComponent component)
  {
    this._colorData = TxObjectCollectionEx.GetInstanceColorsOfObjects(component as ITxObjectCollection);
  }

  private void CollectVisibility(ITxComponent component)
  {
    this._visibilityData = new List<Tuple<ITxDisplayableObject, TxDisplayableObjectVisibility>>();
    this.AddVisibilityData(component as ITxDisplayableObject);
    foreach (ITxObject allDescendant in (Collection<ITxObject>) (component as ITxObjectCollection).GetAllDescendants((ITxTypeFilter) new TxNoTypeFilter()))
    {
      if (allDescendant is ITxDisplayableObject)
        this.AddVisibilityData(allDescendant as ITxDisplayableObject);
    }
  }

  private void AddVisibilityData(ITxDisplayableObject obj)
  {
    TxDisplayableObjectVisibility visibility = TxGraphicsUtilitiesEx.GetVisibility(obj, false);
    if (visibility != null && visibility != 2)
      return;
    this._visibilityData.Add(new Tuple<ITxDisplayableObject, TxDisplayableObjectVisibility>(obj, visibility));
  }

  private void CollectDisplayModel(ITxComponent component)
  {
    this._displayModeData = TxObjectCollectionEx.GetDisplayModeOfObjects(component as ITxObjectCollection);
  }

  private void ApplyGraphicInstanceInfo(ITxComponent sourceComponent)
  {
    this.ApplyColor();
    this.ApplyVisibility();
    this.ApplyDisplayMode();
  }

  private void ApplyColor()
  {
    if (this._colorData == null)
      return;
    foreach (TxObjectColorData txObjectColorData in this._colorData)
      TxEngineeringDataInternal.SetObjectColorData(txObjectColorData);
  }

  private void ApplyVisibility()
  {
    if (this._visibilityData == null)
      return;
    foreach (Tuple<ITxDisplayableObject, TxDisplayableObjectVisibility> tuple in this._visibilityData)
    {
      if (((ITxObject) tuple.Item1).IsValid())
      {
        if (tuple.Item2 == 2)
          tuple.Item1.Blank();
        else if (tuple.Item2 == null)
          tuple.Item1.Display();
      }
    }
  }

  private void ApplyDisplayMode()
  {
    if (this._displayModeData == null)
      return;
    foreach (TxObjectDisplayModeData objectDisplayModeData in this._displayModeData)
      TxEngineeringDataInternal.SetObjectDisplayMode(objectDisplayModeData);
  }

  private bool ReloadSource(ITxComponent sourceComponent)
  {
    try
    {
      ((sourceComponent as ITxStorable).StorageObject as TxLocalStorage).ReloadFromLibrary();
    }
    catch (Exception ex)
    {
      return false;
    }
    return true;
  }

  private bool SetSourceToModeling(ITxComponent sourceComponent)
  {
    try
    {
      sourceComponent.SetModelingScope();
      if (!sourceComponent.IsOpenForModeling)
      {
        this._status = CApSaveComponentAsNewPrototypeLogic.Status.CannotOpenForModeling;
        return false;
      }
    }
    catch (Exception ex)
    {
      this._status = CApSaveComponentAsNewPrototypeLogic.Status.CannotOpenForModeling;
      return false;
    }
    return true;
  }

  private bool ValidateNewPath(string newFilePath)
  {
    string str = string.Empty;
    if (string.IsNullOrEmpty(newFilePath))
      return false;
    if (!this.IsPathUnderSysroot(newFilePath))
      str = TxApplication.PlatformType != 3 ? this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_PATH_NOT_UNDER_SYSROOT") : this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_PATH_NOT_UNDER_LIBRARY_ROOT");
    else if (Directory.Exists(newFilePath))
      str = this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_PATH_EXISTS");
    if (string.IsNullOrEmpty(str))
      return true;
    int num = (int) TxMessageBox.Show(str, this.GetResourceManager().GetString("SAVE_NEW_COMPONENT_AS_CMD_NAME"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    return false;
  }

  private bool ValidateInitialPath(ref string path)
  {
    if (!this.IsPathUnderSysroot(path))
    {
      this._status = CApSaveComponentAsNewPrototypeLogic.Status.ComponentNotInSysroot;
      return false;
    }
    path = this.FixInitialPath(path);
    return true;
  }

  private string FixInitialPath(string path)
  {
    string str = Directory.GetParent(path).ToString();
    while (str.EndsWith(Path.GetExtension(path)))
      str = Directory.GetParent(str).ToString();
    path = Path.Combine(str, Path.GetFileName(path));
    return path;
  }

  private bool IsPathUnderSysroot(string path)
  {
    return path.ToLower().Contains(TxApplication.SystemRootDirectoryNormalized.ToLower());
  }

  private string GetUniqueComponentName(string fullPath)
  {
    string str1 = Directory.GetParent(fullPath).FullName + "\\";
    string withoutExtension = Path.GetFileNameWithoutExtension(fullPath);
    string str2 = fullPath.Substring(str1.Length + withoutExtension.Length);
    int num = 0;
    string[] strArray;
    for (; Directory.Exists(fullPath); fullPath = string.Concat(strArray))
    {
      ++num;
      strArray = new string[5]
      {
        str1,
        withoutExtension,
        "_",
        num.ToString(),
        str2
      };
    }
    return num == 0 ? withoutExtension : $"{withoutExtension}_{num.ToString()}";
  }

  private ITxComponent GetSourceComponent()
  {
    TxObjectList allItems = TxApplication.ActiveSelection.GetAllItems();
    return ((Collection<ITxObject>) allItems).Count != 1 ? (ITxComponent) null : ((Collection<ITxObject>) allItems)[0] as ITxComponent;
  }

  private ITxComponent CopyComponent(ITxComponent component)
  {
    ITxObjectCollection collection = ((ITxObject) component).Collection;
    bool flag = TxObjectCollectionEx.CanPaste(collection, (ITxObject) component);
    ITxComponent itxComponent;
    try
    {
      if (flag)
      {
        ITxObjectCollection objectCollection = collection;
        TxObjectList txObjectList = new TxObjectList();
        ((Collection<ITxObject>) txObjectList).Add((ITxObject) component);
        itxComponent = ((Collection<ITxObject>) objectCollection.Paste(txObjectList))[0] as ITxComponent;
      }
      else
      {
        TxPhysicalRoot physicalRoot = TxApplication.ActiveDocument.PhysicalRoot;
        TxObjectList txObjectList = new TxObjectList();
        ((Collection<ITxObject>) txObjectList).Add((ITxObject) component);
        itxComponent = ((Collection<ITxObject>) physicalRoot.Paste(txObjectList))[0] as ITxComponent;
      }
    }
    catch (Exception ex)
    {
      this._status = CApSaveComponentAsNewPrototypeLogic.Status.PasteFailed;
      return (ITxComponent) null;
    }
    return itxComponent;
  }

  public static bool IsNewComponent(ITxStorable storableObject)
  {
    return storableObject != null && !(storableObject.StorageObject is TxLibraryStorage) && !(((ITxObject) storableObject).GetAttribute("ORIGINAL_PATH_FOR_LOCAL_COMPONENT") is TxStringAttribute);
  }

  private ResourceManager GetResourceManager()
  {
    return new ResourceManager("DnProcessSimulateCommands.StringTable", this.GetType().Assembly);
  }

  private enum Status
  {
    Unknown,
    CancelClicked,
    ComponentHasNoPrototype,
    EquipmentHasSubComponentWithNoPrototype,
    ComponentNotInSysroot,
    CannotOpenForModeling,
    EndModelingFailed,
    ReloadFailed,
    PasteFailed,
  }
}
